﻿using AjaxControlToolkit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.ServiceModel;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using WellDone.ReportExecutionService;
using WellDone.ReportService;
using WellDone.ServiceReferenceReports;

namespace WellDone
{
    public partial class ReportViewerForm : System.Web.UI.Page
    {
        const string k_Str_AuthenticationWarning = "You are not authorized to view this page";

        string strNetworkCredentialUsername, strNetWorkCredentialPwd, strNetWorkCredentialDomain, strDataSourceName, strDataSourceCredentialUsername,
            strDataSourceCredentialPwd, strReportPath, strReportExecutionServerURL, strReportServerURL;

        ReportExecutionService.ReportExecutionService rsExec;
        ReportService.ReportingService2005 rs;

        byte[] result;
        string reportPath;
        string format;
        string historyID;
        bool forRendering = true;
        ReportService.ParameterValue[] values;
        string devInfo;
        string targetPath;
        string path;
        ReportService.ReportParameter[] parameters;
        string encoding;
        string mimeType;
        string extension;
        ReportExecutionService.Warning[] warnings;
        string[] streamIDs;
        ReportExecutionService.ParameterValue[] parametersvalue;
        ReportService.DataSourceCredentials dataSourceServiceCredentials;
        ReportService.DataSourceCredentials[] credentialsService;
        ExecutionInfo execInfo;
        ExecutionHeader execHeader;

        bool validToken = false;

        private void loadUserSettings()
        {
            strNetworkCredentialUsername = System.Configuration.ConfigurationManager.AppSettings["NetworkCredentialUsername"];
            strNetWorkCredentialPwd = System.Configuration.ConfigurationManager.AppSettings["NetWorkCredentialPwd"];
            strNetWorkCredentialDomain = System.Configuration.ConfigurationManager.AppSettings["NetWorkCredentialDomain"];
            strDataSourceCredentialUsername = System.Configuration.ConfigurationManager.AppSettings["DataSourceCredentialUsername"];
            strDataSourceCredentialPwd = System.Configuration.ConfigurationManager.AppSettings["DataSourceCredentialPwd"];
            strDataSourceName = System.Configuration.ConfigurationManager.AppSettings["DataSourceName"];
            strReportPath = System.Configuration.ConfigurationManager.AppSettings["ReportPath"];
            strReportExecutionServerURL = System.Configuration.ConfigurationManager.AppSettings["ReportExecutionServerURL"];
            strReportServerURL = System.Configuration.ConfigurationManager.AppSettings["ReportServerURL"];
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                try
                {
                    string strServiceAddress = System.Configuration.ConfigurationManager.AppSettings["ServiceAddress"];
                    ServiceOpenRPOSClient client = new ServiceOpenRPOSClient();
                    client.Endpoint.Address = new EndpointAddress(new Uri(strServiceAddress));
                    client.Open();

                    validToken = client.ReportGenerator(Convert.ToInt32(Request.QueryString["Token"])); //validate token to authenticate users
                }
                catch (Exception ex)
                {
                    validToken = false;
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }

                pnlReportGenerate.Visible = validToken;
                pnlErrorMessage.Visible = !validToken;

                if (validToken)
                {
                    lblErrormessage.Text = "";
                    // Load user settings...
                    loadUserSettings();
                    // Get reports...
                    getAllReports();
                }
                else
                {
                    lblErrormessage.Text = k_Str_AuthenticationWarning;
                }
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (ddlReportName.SelectedIndex >= 0)
            {
                loadUserSettings();
                buildParameterSection(ddlReportName.SelectedValue);
            }
        }

        public void getAllReports()
        {
            ddlReportName.Items.Clear();
            try
            {

                // Create a Web service proxy object and set credentials            
                ReportingService2005 rs = new ReportingService2005();
                rs.Url = strReportServerURL;
                rs.Credentials = new NetworkCredential(strNetworkCredentialUsername, strNetWorkCredentialPwd, strNetWorkCredentialDomain);

                // Return a list of catalog items in the report server database
                CatalogItem[] items = rs.ListChildren(strReportPath, true);

                // For each report, display the name and use path as value of the report in a dropdown
                foreach (CatalogItem ci in items)
                {
                    if (ci.Type == ItemTypeEnum.Report) ddlReportName.Items.Add(new ListItem(ci.Name, ci.Path));
                }
                ddlReportName.SelectedIndex = 0;
            }
            catch { }
        }

        protected void buildParameterSection(string ReportName)
        {
            setReportParameter(ReportName);
            if (parameters.Length > 0)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].ValidValues != null)
                    {
                        if (parameters[i].MultiValue == false)
                        {
                            createDynamicDropDownList("DropDownList", parameters[i].ValidValues, parameters[i].Prompt, i + 1, parameters[i].Name, parameters[i].Nullable);
                        }
                        else
                        {
                            createDynamicCheckBoxList("CheckBoxList", parameters[i].ValidValues, parameters[i].Prompt, i + 1, parameters[i].Name, parameters[i].Nullable);
                        }
                    }
                    else if (parameters[i].Type == ReportService.ParameterTypeEnum.DateTime)
                    {
                        createDynamicTextBoxWithDate("TextBox", parameters[i].Prompt, i + 1, parameters[i].Name, parameters[i].Nullable);
                    }
                    else if (parameters[i].Type == ReportService.ParameterTypeEnum.String || parameters[i].Type == ReportService.ParameterTypeEnum.Integer || parameters[i].Type == ReportService.ParameterTypeEnum.Float)
                    {
                        createDynamicTextBox("TextBox", parameters[i].Prompt, i + 1, parameters[i].Name, parameters[i].Nullable);
                    }
                    else if (parameters[i].Type == ReportService.ParameterTypeEnum.Boolean)
                    {
                        createDynamicRadioButtonList("RadioButtonList", parameters[i].Prompt, i + 1, parameters[i].Name, parameters[i].Nullable);
                    }
                }
                tblParameter.Visible = true;
            }
            else
            {
                tblParameter.Visible = false;
            }
        }

        protected void setReportParameter(string ReportName)
        {
            ReportPlaceholder.InnerHtml = "";

            string dsName = strDataSourceName; // we have used this as default DS name in most of our designed reports;
            result = null;
            reportPath = ReportName;
            format = ddlReportFormat.SelectedItem.ToString();
            historyID = null;
            forRendering = true;
            values = null;
            devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

            parameters = null;
            warnings = null;
            streamIDs = null;
            parametersvalue = null;

            rs = new ReportingService2005(); //create report service instance
            rs.Url = strReportServerURL;
            rs.Credentials = new NetworkCredential(strNetworkCredentialUsername, strNetWorkCredentialPwd, strNetWorkCredentialDomain);
            dataSourceServiceCredentials = new ReportService.DataSourceCredentials();

            /*get datasource name used in selected report*/
            try
            {
                ReportService.DataSource[] dsource = rs.GetItemDataSources(reportPath);
                dsName = dsource[0].Name;
            }
            catch { }

            dataSourceServiceCredentials.DataSourceName = dsName;
            dataSourceServiceCredentials.UserName = strDataSourceCredentialUsername;
            dataSourceServiceCredentials.Password = strDataSourceCredentialPwd;
            credentialsService = new ReportService.DataSourceCredentials[] { dataSourceServiceCredentials };

            /*fetch all parameters used in report*/
            try
            {
                parameters = rs.GetReportParameters(ReportName, historyID, forRendering, values, credentialsService);
            }
            catch { }

            /*ReportExecutionService*/
            rsExec = new ReportExecutionService.ReportExecutionService(); //create report execution service instance
            rsExec.Url = strReportExecutionServerURL;
            rsExec.Credentials = new NetworkCredential(strNetworkCredentialUsername, strNetWorkCredentialPwd, strNetWorkCredentialDomain);
        }

        protected byte[] getReportResult(string ReportName, string ReportFormat, List<ParametersValue> parameterList, out string errorMessage)
        {
            errorMessage = "";
            setReportParameter(ReportName);
            parametersvalue = new ReportExecutionService.ParameterValue[parameterList.Count];
            if (parameterList.Count > 0)
            {
                int j = 0;
                foreach (var p in parameterList)
                {
                    parametersvalue[j] = new ReportExecutionService.ParameterValue();
                    parametersvalue[j].Name = p.Name;
                    parametersvalue[j].Value = string.IsNullOrEmpty(p.Value) ? null : p.Value;
                    j = j + 1;
                }
            }

            execInfo = new ExecutionInfo();
            execHeader = new ExecutionHeader();

            rsExec.ExecutionHeaderValue = execHeader;
            execInfo = rsExec.LoadReport(reportPath, historyID);

            try
            {
                String SessionId = rsExec.ExecutionHeaderValue.ExecutionID;
                rsExec.SetExecutionParameters(parametersvalue, "en-us");
                result = rsExec.Render(ReportFormat, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
            }
            catch (Exception ex)
            {
                errorMessage = ex.Message.ToString();
                return null;
            }
            return result;
        }

        public void getPreviewReport(string ReportName, string ReportFormat, List<ParametersValue> hstparameter)
        {
            string tempReport = string.Empty;
            byte[] htmlResult = getReportResult(ReportName, "HTML4.0", hstparameter, out tempReport);

            System.Text.Encoding enc = System.Text.Encoding.UTF8;

            if (htmlResult != null)
            {
                tempReport = enc.GetString(result);
            }
            else tempReport = "<font color='red'><b>Unable to generate Preview for selected report</b></font> <br/><br/>" + tempReport;
            ReportPlaceholder.InnerHtml = tempReport;
            ClientScript.RegisterStartupScript(this.GetType(), "Popup", "ShowPreview();", true);
        }

        public void generateReport(string ReportName, string ReportFormat, List<ParametersValue> hstparameter)
        {
            string errorMessage = string.Empty;
            byte[] outResult = getReportResult(ReportName, ddlReportFormat.SelectedItem.Text, hstparameter, out errorMessage);
            if (outResult != null)
            {
                try
                {
                    ReportName = ddlReportName.SelectedItem.Text;

                    targetPath = Server.MapPath("Reports");

                    if (!System.IO.Directory.Exists(targetPath))
                    {
                        System.IO.Directory.CreateDirectory(targetPath);
                    }

                    path = Server.MapPath("~/Reports/") + ReportName + "." + ReportFormat;


                    FileStream stream = File.Create(path, outResult.Length);
                    stream.Write(outResult, 0, outResult.Length);
                    stream.Flush();
                    stream.Dispose();
                    System.IO.FileInfo file = new System.IO.FileInfo(path);
                    if (file.Exists)
                    {
                        Response.Clear();
                        Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
                        Response.AddHeader("Content-Length", file.Length.ToString());
                        Response.ContentType = "application/" + ReportFormat;
                        Response.TransmitFile(path);
                    }
                }
                catch (Exception ex)
                {
                    errorMessage = ex.Message.ToString();
                }
            }
            else
            {
                errorMessage = "<font color='red'><b>Unable to generate selected report</b></font><br/><br/>" + errorMessage;
                ReportPlaceholder.InnerHtml = errorMessage;
                ClientScript.RegisterStartupScript(this.GetType(), "Popup", "ShowPreview();", true);
            }
        }

        public void createDynamicLabel(HtmlGenericControl tr, string lblName, int k, string name, bool nullable)
        {
            HtmlGenericControl td1 = new HtmlGenericControl("td");

            Label lbl = new Label();
            lbl.ID = "Label" + k;
            lbl.Text = lblName;
            td1.Controls.Add(lbl);

            if (nullable == false) //show asterisk if parameter is required to set value
            {
                Label lblRequire = new Label();
                lblRequire.ForeColor = System.Drawing.Color.Red;
                lblRequire.Text = " *";
                td1.Controls.Add(lblRequire);
            }

            tr.Controls.Add(td1);
        }

        public void createDynamicTextBoxWithDate(string _TextBoxId, string lblName, int k, string name, bool nullable)
        {
            HtmlGenericControl tr = new HtmlGenericControl("tr");
            createDynamicLabel(tr, lblName, k, name, nullable); //create label for date picker

            HtmlGenericControl td2 = new HtmlGenericControl("td");
            TextBox txtBox = new TextBox();
            txtBox.ID = _TextBoxId.Replace(" ", "").ToLower() + k;

            txtBox.Attributes.Add("ParameterName", name); //actual parameter name in report, which will be used to set parameter value;

            if (nullable == false) txtBox.Attributes.Add("Class", "required");

            td2.Controls.Add(txtBox);
            tr.Controls.Add(td2);

            HtmlGenericControl td3 = new HtmlGenericControl("td");
            CalendarExtender calExender = new CalendarExtender();
            calExender.PopupPosition = CalendarPosition.Right;
            calExender.ID = "calExender" + k;
            calExender.TargetControlID = txtBox.ID;
            td3.Controls.Add(calExender);
            tr.Controls.Add(td3);

            ParameterPlaceHolder.Controls.Add(tr);
        }

        public void createDynamicTextBox(string _TextBoxId, string lblName, int k, string name, bool nullable)
        {
            HtmlGenericControl tr = new HtmlGenericControl("tr");

            createDynamicLabel(tr, lblName, k, name, nullable); //create label for textbox

            HtmlGenericControl td2 = new HtmlGenericControl("td");
            TextBox txtBox = new TextBox();
            txtBox.ID = _TextBoxId.Replace(" ", "").ToLower() + k;
            txtBox.Attributes.Add("ParameterName", name); //actual parameter name in report, which will be used to set parameter value;
            if (nullable == false) txtBox.Attributes.Add("Class", "required");

            td2.Controls.Add(txtBox);
            tr.Controls.Add(td2);
            ParameterPlaceHolder.Controls.Add(tr);
        }

        public void createDynamicDropDownList(string _ddlId, ReportService.ValidValue[] valid, string lblName, int k, string name, bool nullable)
        {
            HtmlGenericControl tr = new HtmlGenericControl("tr");

            createDynamicLabel(tr, lblName, k, name, nullable); //create label for dropdown control

            HtmlGenericControl td2 = new HtmlGenericControl("td");
            DropDownList ddl = new DropDownList();

            ddl.ID = _ddlId.Replace(" ", "").ToLower() + k;

            ddl.Attributes.Add("ParameterName", name); //actual parameter name in report, which will be used to set parameter value;

            ddl.AutoPostBack = false;

            if (nullable == true)
            {
                ddl.Items.Add(new ListItem("Select " + lblName, "-1"));
            }

            foreach (ReportService.ValidValue v in valid)
            {
                ddl.Items.Add(new ListItem(v.Label, v.Value));
            }
            ddl.SelectedIndex = 0;
            td2.Controls.Add(ddl);
            tr.Controls.Add(td2);
            ParameterPlaceHolder.Controls.Add(tr);
        }

        public void createDynamicRadioButtonList(string _RadioButtonId, string lblName, int k, string name, bool nullable)
        {
            HtmlGenericControl tr = new HtmlGenericControl("tr");
            createDynamicLabel(tr, lblName, k, name, nullable); //create label for radio button

            HtmlGenericControl td2 = new HtmlGenericControl("td");

            RadioButtonList rdl = new RadioButtonList();
            rdl.ID = _RadioButtonId.Replace(" ", "").ToLower() + k;
            rdl.Items.Add(new ListItem("True", "True"));
            rdl.Items.Add(new ListItem("False", "False"));
            rdl.Attributes.Add("ParameterName", name); //actual parameter name in report, which will be used to set parameter value;
            rdl.SelectedIndex = 0;

            td2.Controls.Add(rdl);
            tr.Controls.Add(td2);
            ParameterPlaceHolder.Controls.Add(tr);
        }

        public void createDynamicCheckBoxList(string _chklId, ReportService.ValidValue[] valid, string lblName, int k, string name, bool nullable)
        {
            HtmlGenericControl tr = new HtmlGenericControl("tr");

            createDynamicLabel(tr, lblName, k, name, nullable); //create label for checkbox list

            HtmlGenericControl td2 = new HtmlGenericControl("td");

            HtmlGenericControl div = new HtmlGenericControl("div");
            div.Style.Value = "height:90px;overflow:auto;";

            CheckBoxList chkl = new CheckBoxList();
            chkl.ID = _chklId.Replace(" ", "").ToLower() + k;
            chkl.Attributes.Add("ParameterName", name); //actual parameter name in report, which will be used to set parameter value;
            if (nullable == true)
            {
                chkl.Attributes.Add("Class", "required");
                chkl.Items.Add(new ListItem("Select " + lblName, "-1"));
            }
            foreach (ReportService.ValidValue v in valid)
            {
                chkl.Items.Add(new ListItem(v.Label, v.Value));
            }
            chkl.SelectedIndex = 0;

            div.Controls.Add(chkl); //add checkbox list in Div to prevent showing all list items
            td2.Controls.Add(div);
            tr.Controls.Add(td2);
            ParameterPlaceHolder.Controls.Add(tr);
        }

        protected void btnReport_Click(object sender, EventArgs e)
        {
            lblValidateError.Text = "";
            generateReport(ddlReportName.SelectedValue, ddlReportFormat.SelectedValue, getParametersValue());
        }

        protected void btnPreview_Click(object sender, EventArgs e)
        {
            lblValidateError.Text = "";
            getPreviewReport(ddlReportName.SelectedValue, ddlReportFormat.SelectedValue, getParametersValue());
        }

        public List<ParametersValue> getParametersValue()
        {
            List<ParametersValue> lstValues = new List<ParametersValue>();

            for (int k = 0; k < ParameterPlaceHolder.Controls.Count; k++)
            {
                int j = k + 1;
                string txtId = "TextBox" + j;
                string ddlId = "DropDownList" + j;
                string lblId = "Label" + j;
                string chkId = "CheckBoxList" + j;
                string rblId = "RadioButtonList" + j;

                Label lbl = (Label)ParameterPlaceHolder.FindControl(lblId);
                TextBox txt = (TextBox)ParameterPlaceHolder.FindControl(txtId);
                DropDownList ddl = (DropDownList)ParameterPlaceHolder.FindControl(ddlId);
                CheckBoxList chkl = (CheckBoxList)ParameterPlaceHolder.FindControl(chkId);
                RadioButtonList rbl = (RadioButtonList)ParameterPlaceHolder.FindControl(rblId);


                if (ddl != null)
                {
                    lstValues.Add(new ParametersValue(ddl.Attributes["ParameterName"], ddl.SelectedValue));
                }
                else if (txt != null)
                {
                    lstValues.Add(new ParametersValue(txt.Attributes["ParameterName"], txt.Text));
                }
                else if (chkl != null)
                {
                    foreach (ListItem l in chkl.Items)
                    {
                        if (l.Selected)
                        {
                            lstValues.Add(new ParametersValue(chkl.Attributes["ParameterName"], l.Value));
                        }
                    }
                }
                else if (rbl != null)
                {
                    lstValues.Add(new ParametersValue(rbl.Attributes["ParameterName"], rbl.SelectedValue));
                }
            }
            return lstValues;
        }
    }

    /*custom class to store parameter values to use as input in report execution*/
    public class ParametersValue
    {
        private string _value;
        public string Value
        {
            get
            {
                return this._value;
            }
            set
            {
                this._value = value;
            }
        }

        private string _text;
        public string Name
        {
            get
            {
                return this._text;
            }
            set
            {
                this._text = value;
            }
        }

        public ParametersValue()
        {
        }

        public ParametersValue(string text, string value)
        {
            this.Value = value;
            this.Name = text;
        }
    }
}